import { useNavigate,useLocation } from "react-router-dom"
import React,{ useEffect,useMemo,useState } from "react"
import request from "./request"

import store from "../store"
// 页面访问权限限制
//高阶组件，纯函数，传的参数是组件，返回的是新组件，闭包的原理
export function withAuth(InnerComponent){
    //innercomponent传进来的组件
    //newInner返回的新组件
    function NewInner(props){
        //如果有用户信息就返回原来的组件，如果没有值就跳到登陆
        //先获取本地存储信息
        // console.log('withAuth',props)
        const navigate = useNavigate()
        const location = useLocation()
        // const userInfo = localStorage.getItem('userInfo')
        // //把字符串转对象
        // try{
        //     userInfo = JSON.parse(userInfo)
        // }catch(err){

        // }
        useEffect(()=>{
            //判断用户是否登陆（在后端判断）
            if(!props.user){
                navigate('/login?target='+location.pathname)
            }else{
                //如果有用户信息要校验是否正确，有没有被篡改
                const {authorization} = props.user
                //把令牌发送给后端校验
                request.get('/user/verify',{ 
                    // data:{},//请求体
                    // params:{},//params通过？后的参数传递
                    headers:{
                        authorization:authorization
                    },//请求头
                }).then(({data})=>{
                    if(data.code === 401){
                        navigate('/login?target='+location.pathname)
                    }
                })
            }
        },[])
        return <InnerComponent {...props}/>
    }
    return withUser(NewInner)
}

//代理props
export function withUser(InnerComponent){
    function OutUser(props){
        
        let userInfo = localStorage.getItem('userInfo')
        const navigate = useNavigate()
        //把字符串转对象
        try{
            userInfo = JSON.parse(userInfo)
        }catch(err){

        }
        useEffect(()=>{
            if(!userInfo){
                navigate('/login')
            }
        },[])
        console.log('props', props,'userInfo',userInfo)
        return <InnerComponent {...props} user={userInfo}/>
    }
    return OutUser
}

export function withRedux(InnerComponent){
     return function outerComponent(props){
        const [state,setState] = useState(store.getState())
        //监听Redux数据修改
        store.subscribe(()=>{
            setState(store.getState())
        })
        return <InnerComponent  {...props} {...state} dispatch={store.dispatch}/>
     }
}

//封装一个用户可以自定义的高阶组件,mapStateToProps:第一个回调获取数据，mapDispatchToprops第二个回调修改数据
export function withStore(mapStateToProps,mapDispatchToprops){
    //这个才是真正的高阶组件
    return function hoc(InnerComponent){
        //高阶组件里面需要返回一个组件
        return function outerComponet(props){
            //获取redux数据，并作为组件的状态,把state传入mapStateToProps，让用户拿到state
            const [state,setState] = useState(store.getState())
            const stateProps = useMemo(()=>{
                let res = {}
                try{
                    //调用mapStateToProps才能得到用户传进来的数据（例如：a:10）
                    res = mapStateToProps(state) || {}
                }catch(err){

                }
                return res
            },[state])
            //定义修改数据的方法
            const setDispatch = useMemo(()=>{
                let res = {}
                try{
                    //调用mapStateToProps才能得到用户传进来的数据（例如：a:10）
                    res = mapDispatchToprops(store.dispatch) || {}
                }catch(err){

                }
                return res
            },[state])
            useEffect(()=>{
                //监听redux数据修改，刷新组件
                store.subscribe(()=>{
                    setState(store.getState())
                })
            },[])
           
            return <InnerComponent {...props} {...stateProps} {...setDispatch}/>
        }
    }
}

//使用示例
// withStore(
//     //传回调函数
//     function(state){
//         //想往withStore传什么就return什么
//         return {
//             a:10
//         }
//     }
//     )(InnerComponent)
